home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / umich / music / eked-m1.zoo / src / gm / key_man.c < prev    next >
C/C++ Source or Header  |  1995-02-19  |  5KB  |  183 lines

  1. /*
  2.  *  EKED-M1 : Editor for Korg M1 synth; key_man.c : keyboard equivalents
  3.  *  Copyright (C) 1995 Steven M. Eker (Steven.Eker@brunel.ac.uk)
  4.  *
  5.  *  This program is free software; you can redistribute it and/or modify
  6.  *  it under the terms of the GNU General Public License as published by
  7.  *  the Free Software Foundation; either version 2 of the License, or
  8.  *  (at your option) any later version.
  9.  *
  10.  *  This program is distributed in the hope that it will be useful,
  11.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  *  GNU General Public License for more details.
  14.  *
  15.  *  You should have received a copy of the GNU General Public License
  16.  *  along with this program; if not, write to the Free Software
  17.  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  */
  19.  
  20. #include <stddef.h>
  21. #include <string.h>
  22. #include <ctype.h>
  23. #include <osbind.h>
  24. #include <gemfast.h>
  25. #include "gem_man.h"
  26.  
  27. /*
  28.  *    shift_code =    00000000 0000ACLR    (alt, ctrl, left, right)
  29.  *    scan_code =    00000000 0sssssss
  30.  *    lookup code =    000000ss sssssACS    where S = L|R
  31.  */
  32. #define KE_CODE(s, r)    (((s) >> 1) | ((s) & 1) | ((r) << 3))
  33. #define KE_HASH(c)    (((unsigned) (c)) % MAX_EQUIV)
  34.  
  35. typedef struct {
  36.   char *name;            /* Key name as it appears in menu */
  37.   char code;            /* scancode */
  38. } NAMED_KEY;
  39.  
  40. static KEY_EQUIV ke_table[MAX_EQUIV];
  41.  
  42. static void check_for_equiv(int title, int item, char *string);
  43. static int ascii2key(char c);
  44.  
  45. KEY_EQUIV *km_get_equiv(int shift_code, int scan_code)
  46. {
  47.   int c = KE_CODE(shift_code, scan_code);
  48.   KEY_EQUIV *start = ke_table + KE_HASH(c), *k = start;
  49.  
  50.   do{
  51.     if(k->code == c)
  52.       return k;
  53.     if(k->code == 0)    /* most key combinations won't be equivalents! */
  54.       break;
  55.     if(++k == ke_table + MAX_EQUIV)
  56.       k = ke_table;
  57.   }while(k != start);
  58.   return NULL;
  59. }
  60.   
  61. void km_set_equiv(int shift_code, int scan_code, int title, int item)
  62. {
  63.   int c = KE_CODE(shift_code, scan_code);
  64.   KEY_EQUIV *start = ke_table + KE_HASH(c), *k = start;
  65.  
  66.   do{
  67.     if(k->code == c || k->code == 0){
  68.       k->code = c;
  69.       k->title = title;
  70.       k->item = item;
  71.       return;
  72.     }
  73.     if(++k == ke_table + MAX_EQUIV)
  74.       k = ke_table;
  75.   }while(k != start);
  76. }
  77.   
  78. void km_scan_menu(OBJECT *menu)
  79. {
  80.   int active = menu[menu[0].ob_head].ob_head, dropdown = menu[0].ob_tail;
  81.   int t, b, i;
  82.  
  83.   for(t = menu[menu[active].ob_head].ob_next,
  84.       b = menu[menu[dropdown].ob_head].ob_next;
  85.       t != active && b != dropdown; t = menu[t].ob_next, b = menu[b].ob_next){
  86.     for(i = menu[b].ob_head; i != b; i = menu[i].ob_next)
  87.       check_for_equiv(t, i, (char *) menu[i].ob_spec);
  88.   }
  89. }
  90.  
  91. static void check_for_equiv(int title, int item, char *string)
  92. {
  93.   static NAMED_KEY misc[] = {
  94.     {"Tab", 0x0F},    {"Esc", 0x01},    {"ClrHome", 0x47},    {"Del", 0x53},
  95.     {"Undo", 0x61},    {"Bksp", 0x0E},    {"Help", 0x62},        {"Enter", 0x72},
  96.     {"Ins", 0x52},    {"Ret", 0x1C},    {NULL, 0x00}
  97.   };
  98.   int i, c, n, start, end, seeking_space, shift_code, scan_code;
  99.   size_t l;
  100.   NAMED_KEY *p;
  101.  
  102.   n = 0;
  103.   seeking_space = 0;
  104.   for(i = 0; string[i]; i++){
  105.     if(isspace(string[i])){
  106.       if(seeking_space){
  107.         end = i - 1;
  108.         seeking_space = 0;
  109.       }
  110.     }
  111.     else{
  112.       if(!seeking_space){
  113.         n++;
  114.         start = i;
  115.         seeking_space = 1;
  116.       }
  117.     }
  118.   }
  119.   if(n < 2)
  120.     return;
  121.   if(seeking_space)
  122.     end = i - 1;
  123. /*
  124.  *    More than two words; last word is string[start]...string[end]
  125.  *    Check for modifiers
  126.  */
  127.   shift_code = 0;
  128.   for(i = start; i < end; i++){
  129.     c = string[i];
  130.     if(c == 0x01)
  131.       shift_code |= 1;    /* shift */
  132.     else if(c == '^')
  133.       shift_code |= 4;    /* control */
  134.     else if(c == 0x07)
  135.       shift_code |= 8;    /* alternate */
  136.     else
  137.       break;
  138.   }
  139. /*
  140.  *    Check for a valid key name
  141.  */
  142.   scan_code = -1;
  143.   if(i == end)    /* one character - assume ASCII */
  144.     scan_code = ascii2key(string[i]);
  145.   else if(string[i] == 'F' && isdigit(string[i + 1]) && i + 2 <= end){
  146.     n = string[i + 1] - '0';
  147.     if(i + 2 == end)
  148.       n = isdigit(string[i + 2]) ? 10 * n + string[i + 2] - '0' : 0;
  149.     if(n >= 1){
  150.       if(n <= 10)
  151.         scan_code = (0x3B - 1) + n;
  152.       else if(n <= 20)
  153.         scan_code = (0x54 - 11) + n;
  154.     }
  155.   }
  156.   else{
  157.     for(p = misc; p->code; p++){
  158.       l = strlen(p->name);
  159.       if(end - i + 1 == l && strncmp(string + i, p->name, l) == 0){
  160.         scan_code = p->code;
  161.         break;
  162.       }
  163.     }
  164.   }
  165.   if(scan_code > 0)
  166.     km_set_equiv(shift_code, scan_code, title, item);
  167. }
  168.  
  169. static int ascii2key(char c)
  170. {
  171.   _KEYTAB *p = Keytbl((char *) -1, (char *) -1, (char *) -1);
  172.   char *unshift = p->unshift, *shift = p->shift, *caps = p->caps;
  173.   int i;
  174.  
  175.   for(i = 0; i <= 127; i++){
  176.     if(unshift[i] == c || shift[i] == c || caps[i] == c)
  177.       return i;
  178.   }
  179.   return -1;
  180. }
  181.  
  182.   
  183.